import type { App, Directive } from 'vue'
import { throttleRAF } from '../loash'
import { typeCheck } from '../types'

// 自定义命令
export class OwnDirective {
  directiveArr: { name: string; directive: Directive }[] = [
    { name: 'debounce', directive: this.debounce() },
  ]
  constructor(app: App) {
    // 注册自定义命令
    for (let item of this.directiveArr) {
      app.directive(item.name, item.directive)
    }
  }

  /**
   * 参数类型检查
   * @param date 需要检查的数据
   * @param type 正确的类型
   * @param errMsg
   */
  static _typeCheck(data: any, type: string, errMsg?: string) {
    const _errMsg = errMsg ? errMsg : `${data} should be a ${type}.`
    const isValid = typeCheck(data, type)
    if (!isValid) {
      throw Error(_errMsg)
    }
  }

  // 防抖事件调度自定义命令
  debounce(): Directive {
    return {
      mounted($el, binding) {
        OwnDirective._typeCheck(binding.value, 'array')
        const type = binding.value[0]
        const exc = binding.value[1]
        const delay = binding.value[3]
        if (!type || !exc) throw new Error(`参数传递缺失, 传入的参数为 0: ${type} 1: ${exc}`)
        OwnDirective._typeCheck(type, 'string', `arr[0] should be a string.`)
        OwnDirective._typeCheck(exc, 'function', `arr[1] should be a function`)
        const eventHandler = throttleRAF(exc, { leading: false, delay: delay ?? 500 }).debounce
        $el.addEventListener(type, eventHandler)
        $el._event_throttle_ = eventHandler
      },
      unmounted($el, binding) {
        const type = binding.value[0]
        $el.removeEventListener(type, $el._event_throttle_)
      },
    }
  }
}
